package logger

import (
	"sync"
)

type IAlloc func() interface{}
type IRelease interface {
	Release()
}

type IDiscard interface {
	Discard()
}

// pool 内存池
type pool struct {
	idles       []interface{}
	r           int
	w           int
	full        bool
	constructor IAlloc
	lock        sync.Mutex
}

func (c *pool) Init(n int, constructor IAlloc) *pool {
	if n <= 0 {
		n = 10
	}
	c.idles = make([]interface{}, n)
	for i := 0; i < n; i++ {
		c.idles[i] = constructor()
	}
	c.r, c.w, c.full, c.constructor = 0, 0, true, constructor
	return c
}

func (c *pool) Alloc() interface{} {
	c.lock.Lock()
	if c.r == c.w {
		if !c.full {
			c.lock.Unlock()
			return c.constructor()
		}
		c.full = false
	}
	n := len(c.idles)
	v := c.idles[c.r]
	c.r = (c.r + 1) % n
	c.lock.Unlock()
	return v
}

func (c *pool) Release(rat interface{}) {
	if rat == nil {
		return
	}
	if v, ok := rat.(IRelease); ok {
		v.Release()
	}
	c.lock.Lock()
	n := len(c.idles)
	if c.full {
		c.lock.Unlock()
		if v, ok := rat.(IDiscard); ok {
			v.Discard()
		}
		return
	}
	c.idles[c.w] = rat
	c.w = (c.w + 1) % n
	c.full = c.w == c.r
	c.lock.Unlock()
}
